package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.repository.IStrategySearchRepository;
import cn.wolfcode.luowowo.serach.query.SearchQueryObject;
import cn.wolfcode.luowowo.serach.service.IStrategySearchService;
import cn.wolfcode.luowowo.serach.template.StrategyTemplate;
import cn.wolfcode.luowowo.serach.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

/**
 * Created by admin on 2019/8/17.
 */
@Service
public class StrategySearchServiceImpl implements IStrategySearchService {

    @Autowired
    private IStrategySearchRepository repository;

    @Autowired
    private ElasticsearchTemplate template;


    @Override
    public void saveOrUpdate(StrategyTemplate strategyTemplate) {
        repository.save(strategyTemplate);
    }

    // 主题推荐
    @Override
    public List<Map<String, Object>> getThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();
        List<StatisVO> themes = this.statisgroup("themeId", "themeName", "groupByThemeId");
        // 截取前十个
        List<StatisVO> subList = null;
        if (themes.size() > 10) {
            subList = themes.subList(0, 10);
        } else {
            subList = themes.subList(0, themes.size());
        }

        for (StatisVO theme : subList) {
            List<StatisVO> dest = this.getDestByThemeId(theme.getId());
            HashMap<String, Object> map = new HashMap<>();
            map.put("theme", theme);
            map.put("dests", dest);
            data.add(map);
        }
        return data;
    }

    // 根据主题Id查询目的地
    private List<StatisVO> getDestByThemeId(Long themeId) {
        Iterable<StrategyTemplate> iterator = repository.search(QueryBuilders.termQuery("themeId", themeId));
        List<StatisVO> dest = new ArrayList<>();

        List<String> temp = new ArrayList<>();

        iterator.forEach(st -> {
            if (!temp.contains(st.getDestName())) {
                StatisVO vo = new StatisVO();
                vo.setId(st.getDestId());
                vo.setName(st.getDestName());
                dest.add(vo);
                temp.add(st.getDestName());
            }
        });
        return dest;
    }


    // 条件查询
    @Override
    public List<StatisVO> getConditionGroup(int type) {

        String idField = "";
        String nameField = "";
        if (type == SearchQueryObject.CONDITION_TYPE_ABROAD) {
            idField = "countryId";
            nameField = "countryName";
        } else if (type == SearchQueryObject.CONDITION_TYPE_UN_ABROAD) {
            idField = "provinceId";
            nameField = "provinceName";
        } else if (type == SearchQueryObject.CONDITION_TYPE_THEME) {
            idField = "themeId";
            nameField = "themeName";
        }
        return this.statisgroup(idField, nameField, "conditionGroup");
    }

    // 条件分页查询
    @Override
    public Page query(SearchQueryObject qo) {

        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        if (qo.getType() == SearchQueryObject.CONDITION_TYPE_ABROAD) {
            boolQuery.must(QueryBuilders.termQuery("countryId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_UN_ABROAD) {
            boolQuery.must(QueryBuilders.termQuery("provinceId", qo.getTypeValue()));
        } else if (qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME) {
            boolQuery.must(QueryBuilders.termQuery("themeId", qo.getTypeValue()));
        }
        return repository.search(boolQuery, qo.getPageable());
    }


    // 分组查询出主题数据
    private List<StatisVO> statisgroup(String idField, String nameField, String conditionGroup) {

        // 拼接source
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();

        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.missingBucket(true);
        idSource.field(idField);
        sources.add(idSource);

        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.missingBucket(true);
        nameSource.field(nameField);
        sources.add(nameSource);

        // 拼接 aggs
        CompositeAggregationBuilder aggsBuilder = new CompositeAggregationBuilder(conditionGroup, sources);

        // 拼接发送请求路径
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);
        builder.addAggregation(aggsBuilder);
        // 发送搜索请求
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        // 返回数据
        InternalComposite aggregation = page.getAggregations().get(conditionGroup);
        List<StatisVO> themes = new ArrayList<>();
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            Map<String, Object> key = bucket.getKey();
            StatisVO vo = new StatisVO();
            if (key.get("id") == null || key.get("name") == null) {
                continue;
            }
            vo.setId(Long.parseLong(key.get("id").toString()));
            vo.setName(key.get("name").toString());
            vo.setCount(Long.parseLong(bucket.getDocCount() + ""));
            themes.add(vo);
        }
        // 排序
        Collections.sort(themes, new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                return Integer.valueOf(o2.getCount() - o1.getCount() + "");
            }
        });
        return themes;
    }

    // 根据目的地名查所有攻略
    @Override
    public List<StrategyTemplate> findByName(String name) {
        return repository.findByDestName(name);
    }
}
